#include "compileoptiondialog.h"
#include "globalvar.h"

CompileOptionDialog::CompileOptionDialog(QWidget *parent) : QDialog(parent)
{
    this->setFixedSize(520, 480);
    this->setWindowTitle(tr("Compiler Configuration"));
    QVBoxLayout *mainVLayout = new QVBoxLayout; //定义垂直布局器
    this->setLayout(mainVLayout);//将mainVLayout设定为本窗口的布局器

    gccButton = new QPushButton;
    gppButton = new QPushButton;
    makeButton = new QPushButton;
    gdbButton = new QPushButton;
    windresButton = new QPushButton;
    gprofButton = new QPushButton;

    questionButton = new QPushButton;

    gccLineEdit = new QLineEdit;
    gppLineEdit = new QLineEdit;
    makeLineEdit = new QLineEdit;
    gdbLineEdit = new QLineEdit;
    windresLineEdit = new QLineEdit;
    gprofLineEdit = new QLineEdit;

    compilerComboBox = new QComboBox;
    modeLabel=new QLabel(tr("Compile Mode:"));
    modeComboBox = new QComboBox;
    compileArgTextEdit = new QPlainTextEdit;
    linkArgTextEdit = new QPlainTextEdit;
    compileArgCheckBox = new QCheckBox(tr("Compiler Options:"));
    linkArgCheckBox = new QCheckBox(tr("Link Options:"));
    staticLinkCheckBox=new QCheckBox(tr("Link statically"));
    warningAllCheckBox=new QCheckBox(tr("Show general warnings"));
    warningExtraCheckBox=new QCheckBox(tr("Show extra warnings"));

    addNewSetButton = new QPushButton;
    addSetFromPathButton = new QPushButton;
    compilerRenameButton = new QPushButton;
    removeSetButton = new QPushButton;

    okButton = new QPushButton(tr("OK")); //定义OK按钮
    cancelButton = new QPushButton(tr("Cancel")); //定义取消按钮

    directoriesWidget = new DirectoriesWidget(this);

    //***********Compiler GroupBox*********************************************
    QGroupBox *compilerGroupBox = new QGroupBox(tr("Current Compiler"));
    compilerComboBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);

    compilerRenameButton->setIcon(QPixmap(":images/rename.png"));
    compilerRenameButton->setToolTip(tr("Rename the current compiler"));
    compilerRenameButton->setFocusPolicy(Qt::NoFocus);
    connect(compilerRenameButton, &QPushButton::clicked, this, &CompileOptionDialog::compilerRenameButtonClicked);

    addSetFromPathButton->setIcon(QPixmap(":images/addByFolder.png"));
    addSetFromPathButton->setToolTip(tr("Add a compiler by folder"));
    addSetFromPathButton->setFocusPolicy(Qt::NoFocus);
    connect(addSetFromPathButton, &QPushButton::clicked, this, &CompileOptionDialog::addSetFromPathButtonClicked);

    addNewSetButton->setIcon(QPixmap(":images/addNew.png"));
    addNewSetButton->setToolTip(tr("Add a blank compiler"));
    addNewSetButton->setFocusPolicy(Qt::NoFocus);
    connect(addNewSetButton, &QPushButton::clicked, this, &CompileOptionDialog::addNewSetButtonClicked);

    removeSetButton->setIcon(QPixmap(":images/remove.png"));
    removeSetButton->setToolTip(tr("Remove the selected compiler"));
    removeSetButton->setFocusPolicy(Qt::NoFocus);
    connect(removeSetButton, &QPushButton::clicked, this, &CompileOptionDialog::removeSetButtonClicked);

    QHBoxLayout *compilerHLayout = new QHBoxLayout; //定义水平布局器compilerHLayout
    compilerHLayout->addWidget(compilerComboBox);
    compilerHLayout->addWidget(addNewSetButton);
    compilerHLayout->addWidget(addSetFromPathButton);
    compilerHLayout->addWidget(compilerRenameButton);
    compilerHLayout->addWidget(removeSetButton);
    compilerGroupBox->setLayout(compilerHLayout);

    QTabWidget *topTabWidget = new QTabWidget;

    //*********General page***********************
    QWidget *generalWidget = new QWidget;

    modeComboBox->setPlaceholderText(tr("Compilation Mode"));
    modeComboBox->addItems(QStringList{"Custom","Debug","Profile","Release"});
    modeComboBox->setToolTip(tr("Compilation Mode"));

    questionButton->setIcon(QPixmap(":images/question.png"));
    questionButton->setFixedWidth(24);

    connect(questionButton, &QPushButton::clicked, this, &CompileOptionDialog::questionButtonClicked);

    QVBoxLayout *generalWidgetVLayout = new QVBoxLayout;
    QHBoxLayout *compilerArgHLayout = new QHBoxLayout;
    generalWidgetVLayout->addLayout(compilerArgHLayout);
    compilerArgHLayout->addWidget(compileArgCheckBox);
    compilerArgHLayout->addStretch();
    compilerArgHLayout->addWidget(modeLabel);
    compilerArgHLayout->addWidget(modeComboBox);
    compilerArgHLayout->addWidget(questionButton);

    generalWidget->setLayout(generalWidgetVLayout);

    generalWidgetVLayout->addWidget(compileArgTextEdit);
    generalWidgetVLayout->addWidget(linkArgCheckBox);
    generalWidgetVLayout->addWidget(linkArgTextEdit);

    QHBoxLayout *warningsHLayout = new QHBoxLayout;
    generalWidgetVLayout->addLayout(warningsHLayout);
    warningsHLayout->addWidget(staticLinkCheckBox);
    warningsHLayout->addWidget(warningAllCheckBox);
    warningsHLayout->addWidget(warningExtraCheckBox);

    compileArgCheckBox->setChecked(true);
    compileArgTextEdit->setEnabled(true);
    compileArgTextEdit->setStyle(QStyleFactory::create("windows"));
    linkArgCheckBox->setChecked(false);
    linkArgTextEdit->setEnabled(false);
    linkArgTextEdit->setStyle(QStyleFactory::create("windows"));

    connect(compileArgCheckBox, &QCheckBox::checkStateChanged, this, &CompileOptionDialog::compileArgCheckBoxStateChanged);
    connect(linkArgCheckBox, &QCheckBox::checkStateChanged, this, &CompileOptionDialog::linkArgCheckBoxStateChanged);

    topTabWidget->addTab(generalWidget, tr("General"));

    //*********Directories page***********************
    topTabWidget->addTab(directoriesWidget, tr("Directories"));

    //*********Programs page***********************
    QWidget *programsWidget = new QWidget;
    QFormLayout *programFormLayout = new QFormLayout;
    programFormLayout->setSpacing(16);
    programsWidget->setLayout(programFormLayout);

    int labelWidth = 60;
    QLabel *gccLabel = new QLabel("gcc:");
    gccLabel->setFixedWidth(labelWidth);
    gccButton->setIcon(QPixmap(":images/folder.png"));
    connect(gccButton, &QPushButton::clicked, this, &CompileOptionDialog::fileButtonClicked);
    QHBoxLayout *gccHLayout = new QHBoxLayout;
    gccHLayout->setSpacing(5);
    gccHLayout->addWidget(gccLabel);
    gccHLayout->addWidget(gccLineEdit);
    gccHLayout->addWidget(gccButton);

    QLabel *gppLabel = new QLabel("g++:");
    gppLabel->setFixedWidth(labelWidth);
    gppButton->setIcon(QPixmap(":images/folder.png"));
    connect(gppButton, &QPushButton::clicked, this, &CompileOptionDialog::fileButtonClicked);
    QHBoxLayout *gppHLayout = new QHBoxLayout;
    gppHLayout->setSpacing(5);
    gppHLayout->addWidget(gppLabel);
    gppHLayout->addWidget(gppLineEdit);
    gppHLayout->addWidget(gppButton);

    QLabel *makeLabel = new QLabel("make:");
    makeLabel->setFixedWidth(labelWidth);
    makeButton->setIcon(QPixmap(":images/folder.png"));
    connect(makeButton, &QPushButton::clicked, this, &CompileOptionDialog::fileButtonClicked);
    QHBoxLayout *makeHLayout = new QHBoxLayout;
    makeHLayout->setSpacing(5);
    makeHLayout->addWidget(makeLabel);
    makeHLayout->addWidget(makeLineEdit);
    makeHLayout->addWidget(makeButton);

    QLabel *gdbLabel = new QLabel("gdb:");
    gdbLabel->setFixedWidth(labelWidth);
    gdbButton->setIcon(QPixmap(":images/folder.png"));
    connect(gdbButton, &QPushButton::clicked, this, &CompileOptionDialog::fileButtonClicked);
    QHBoxLayout *gdbHLayout = new QHBoxLayout;
    gdbHLayout->setSpacing(5);
    gdbHLayout->addWidget(gdbLabel);
    gdbHLayout->addWidget(gdbLineEdit);
    gdbHLayout->addWidget(gdbButton);

    QLabel *windresLabel = new QLabel("windres:");
    windresLabel->setFixedWidth(labelWidth);
    windresLabel->setFixedWidth(60);
    windresButton->setIcon(QPixmap(":images/folder.png"));
    connect(windresButton, &QPushButton::clicked, this, &CompileOptionDialog::fileButtonClicked);
    QHBoxLayout *windresHLayout = new QHBoxLayout;
    windresHLayout->setSpacing(5);
    windresHLayout->addWidget(windresLabel);
    windresHLayout->addWidget(windresLineEdit);
    windresHLayout->addWidget(windresButton);

    QLabel *gprofLabel = new QLabel("gprof:");
    gprofLabel->setFixedWidth(labelWidth);
    gprofButton->setIcon(QPixmap(":images/folder.png"));
    connect(gprofButton, &QPushButton::clicked, this, &CompileOptionDialog::fileButtonClicked);
    QHBoxLayout *gprofHLayout = new QHBoxLayout;
    gprofHLayout->setSpacing(5);
    gprofHLayout->addWidget(gprofLabel);
    gprofHLayout->addWidget(gprofLineEdit);
    gprofHLayout->addWidget(gprofButton);

    programFormLayout->addRow(gccHLayout);
    programFormLayout->addRow(gppHLayout);
    programFormLayout->addRow(makeHLayout);
    programFormLayout->addRow(gdbHLayout);
    programFormLayout->addRow(windresHLayout);
    programFormLayout->addRow(gprofHLayout);

    topTabWidget->addTab(programsWidget, tr("Programs"));

    //OK,Cancel按钮及布局器
    QHBoxLayout *okCancelHLayout = new QHBoxLayout; //定义水平布局器okCancelHLayout
    okCancelHLayout->addStretch();//添加弹簧
    okCancelHLayout->addWidget(okButton);//添加OK按钮到
    okCancelHLayout->addWidget(cancelButton);//添加Cancel按钮到
    okCancelHLayout->addStretch();//添加弹簧

    connect(okButton, &QPushButton::clicked, this, &CompileOptionDialog::okButtonClicked);//OK按钮点击和处理函数的连接
    connect(cancelButton, &QPushButton::clicked, this, &CompileOptionDialog::cancelButtonClicked);//Cancel按钮点击和处理函数的连接

    //主布局器添加控件和布局器
    mainVLayout->addWidget(compilerGroupBox);
    mainVLayout->addWidget(topTabWidget);
    mainVLayout->addLayout(okCancelHLayout);

    loadCompilerSets();

    //如果编译器列表中没有数据，在程序所在目录中寻找编译器
    if (compilerComboBox->count() < 1)
    {
        this->setEnabled(false);
        CompilerSet compilerSet;
        GetDirNameList(QApplication::applicationDirPath(), compilerSet);
        this->setEnabled(true);

        if (!compilerSet.compilerName.isEmpty())//如果找到了编译器
        {
            compilerSet.staticLinkCheckBoxState=true;

            compilerComboBox->addItem(compilerSet.compilerName);
            compilerComboBox->setCurrentText(compilerSet.compilerName);
            QVariant myVariant = QVariant::fromValue(compilerSet); //该结构体实例转换为QVariant
            compilerComboBox->setItemData(compilerComboBox->currentIndex(), myVariant, Qt::UserRole);

            compilerComboBoxCurrentIndexChanged(compilerComboBox->currentIndex());

            writeSettings();//保存编译器数据
        }
    }
}

void CompileOptionDialog::loadCompilerSets()
{
    //读取上次关闭时保存的编译器信息
    QString appDataPath = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
    QSettings setting(appDataPath + "/Setting.ini", QSettings::IniFormat);

    QList<CompilerSet> compilerSetList;
    compilerSetList = setting.value("CompilerSet").value<QList<CompilerSet>>();
    currentIndex = setting.value("CurrentCompilerIndex", -1).toInt();

    disconnect(compilerComboBox, &QComboBox::currentIndexChanged, this, &CompileOptionDialog::compilerComboBoxCurrentIndexChanged);

    compilerComboBox->clear();
    foreach (CompilerSet compilerSet, compilerSetList)
    {
        compilerComboBox->addItem(compilerSet.compilerName, QVariant::fromValue(compilerSet));
        compilerComboBox->setCurrentText(compilerSet.compilerName);
    }

    if (currentIndex != compilerComboBox->currentIndex() && currentIndex >= 0 && currentIndex < compilerComboBox->count())
        compilerComboBox->setCurrentIndex(currentIndex);

    currentIndex = compilerComboBox->currentIndex();
    compilerComboBoxCurrentIndexChanged(compilerComboBox->currentIndex());

    connect(compilerComboBox, &QComboBox::currentIndexChanged, this, &CompileOptionDialog::compilerComboBoxCurrentIndexChanged);
}

QString CompileOptionDialog::getCompileMode()
{
    return modeComboBox->currentText();
}

void CompileOptionDialog::compilerComboBoxCurrentIndexChanged(int index)
{
    if (currentIndex != index && currentIndex >= 0 && currentIndex < compilerComboBox->count())
    {
        if (compilerSetChanged(currentIndex))
        {
            QMessageBox::StandardButton result = QMessageBox::question(this, "Save Changes", "Save Changes to "
                                                                     + compilerComboBox->itemText(currentIndex) + "?", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
            if (result == QMessageBox::Yes)
            {
                saveChangesToCompilerSet(currentIndex);
            }
        }
    }

    CompilerSet compilerSet = compilerComboBox->itemData(index, Qt::UserRole).value<CompilerSet>();
    loadDataFromCompilerSet(compilerSet);
    currentIndex = index;
}

bool CompileOptionDialog::compilerSetChanged(int index)
{
    CompilerSet compilerSet = compilerComboBox->itemData(index, Qt::UserRole).value<CompilerSet>();

    if (gccLineEdit->text() != compilerSet.gccFile) return true;
    if (gppLineEdit->text() != compilerSet.gppFile) return true;
    if (makeLineEdit->text() != compilerSet.makeFile) return true;
    if (gdbLineEdit->text() != compilerSet.gdbFile) return true;
    if (gprofLineEdit->text() != compilerSet.gprofFile) return true;
    if (windresLineEdit->text() != compilerSet.windresFile) return true;

    if (modeComboBox->currentIndex()!=compilerSet.modeIndex) return true;
    if (compileArgCheckBox->isChecked()!=compilerSet.compileArgCheckBoxState) return true;
    if (linkArgCheckBox->isChecked()!=compilerSet.linkArgCheckBoxState) return true;
    if (staticLinkCheckBox->isChecked()!=compilerSet.staticLinkCheckBoxState) return true;
    if (warningAllCheckBox->isChecked()!=compilerSet.warningAllCheckBoxState) return true;
    if (warningExtraCheckBox->isChecked()!=compilerSet.warningExtraCheckBoxState) return true;

    if (compileArgCheckBox->isChecked()&&compilerSet.compileArgCheckBoxState)
        if (compileArgTextEdit->toPlainText() != compilerSet.compileArg) return true;

    if (linkArgCheckBox->isChecked()&&compilerSet.linkArgCheckBoxState)
        if (linkArgTextEdit->toPlainText() != compilerSet.linkArg) return true;

    QListWidget *binListWidget = directoriesWidget->getBinListWidget();
    if (binListWidget->count() != compilerSet.binList.count())
    {
        return true;
    }
    else
    {
        int count = binListWidget->count();
        for (int i = 0; i < count; i++)
        {
            if (compilerSet.binList[i] != binListWidget->item(i)->text())
                return true;
        }
    }

    QListWidget *libListWidget = directoriesWidget->getLibListWidget();
    if (libListWidget->count() != compilerSet.libList.count())
    {
        return true;
    }
    else
    {
        int count = libListWidget->count();
        for (int i = 0; i < count; i++)
        {
            if (compilerSet.libList[i] != libListWidget->item(i)->text())
                return true;
        }
    }

    QListWidget *cIncludeListWidget = directoriesWidget->getCIncludeListWidget();
    if (cIncludeListWidget->count() != compilerSet.cIncludeList.count())
    {
        return true;
    }
    else
    {
        int count = cIncludeListWidget->count();
        for (int i = 0; i < count; i++)
        {
            if (compilerSet.cIncludeList[i] != cIncludeListWidget->item(i)->text())
                return true;
        }
    }

    QListWidget *cppIncludeListWidget = directoriesWidget->getCppIncludeListWidget();
    if (cppIncludeListWidget->count() != compilerSet.cppIncludeList.count())
    {
        return true;
    }
    else
    {
        int count = cppIncludeListWidget->count();
        for (int i = 0; i < count; i++)
        {
            if (compilerSet.cppIncludeList[i] != cppIncludeListWidget->item(i)->text())
                return true;
        }
    }

    return false;
}

void CompileOptionDialog::saveChangesToCompilerSet(int index)
{
    CompilerSet compilerSet;

    compilerSet.compilerName = compilerComboBox->itemText(index);

    compilerSet.compileArg = compileArgTextEdit->toPlainText();
    compilerSet.linkArg = linkArgTextEdit->toPlainText();

    compilerSet.gccFile = gccLineEdit->text();
    compilerSet.gppFile = gppLineEdit->text();
    compilerSet.makeFile = makeLineEdit->text();
    compilerSet.gdbFile = gdbLineEdit->text();
    compilerSet.gprofFile = gprofLineEdit->text();
    compilerSet.windresFile = windresLineEdit->text();

    compilerSet.modeIndex = modeComboBox->currentIndex();
    compilerSet.compileArgCheckBoxState=compileArgCheckBox->isChecked();
    compilerSet.linkArgCheckBoxState=linkArgCheckBox->isChecked();
    compilerSet.staticLinkCheckBoxState=staticLinkCheckBox->isChecked();
    compilerSet.warningAllCheckBoxState=warningAllCheckBox->isChecked();
    compilerSet.warningExtraCheckBoxState=warningExtraCheckBox->isChecked();

    QListWidget *binListWidget = directoriesWidget->getBinListWidget();
    int count = binListWidget->count();
    for (int i = 0; i < count; i++)
        compilerSet.binList.append(binListWidget->item(i)->text());

    QListWidget *libListWidget = directoriesWidget->getLibListWidget();
    count = libListWidget->count();
    for (int i = 0; i < count; i++)
        compilerSet.libList.append(libListWidget->item(i)->text());

    QListWidget *cIncludeListWidget = directoriesWidget->getCIncludeListWidget();
    count = cIncludeListWidget->count();
    for (int i = 0; i < count; i++)
        compilerSet.cIncludeList.append(cIncludeListWidget->item(i)->text());

    QListWidget *cppIncludeListWidget = directoriesWidget->getCppIncludeListWidget();
    count = cppIncludeListWidget->count();
    for (int i = 0; i < count; i++)
        compilerSet.cppIncludeList.append(cppIncludeListWidget->item(i)->text());

    QVariant variant = QVariant::fromValue(compilerSet); //该结构体实例转换为QVariant
    compilerComboBox->setItemData(index, variant, Qt::UserRole);
}

void CompileOptionDialog::loadDataFromCompilerSet(CompilerSet compilerSet)
{
    compileArgTextEdit->setPlainText(compilerSet.compileArg);
    linkArgTextEdit->setPlainText(compilerSet.linkArg);
    gccLineEdit->setText(compilerSet.gccFile);
    gppLineEdit->setText(compilerSet.gppFile);
    makeLineEdit->setText(compilerSet.makeFile);
    gdbLineEdit->setText(compilerSet.gdbFile);
    gprofLineEdit->setText(compilerSet.gprofFile);
    windresLineEdit->setText(compilerSet.windresFile);

    compileArgCheckBox->setChecked(compilerSet.compileArgCheckBoxState);
    linkArgCheckBox->setChecked(compilerSet.linkArgCheckBoxState);
    staticLinkCheckBox->setChecked(compilerSet.staticLinkCheckBoxState);
    warningAllCheckBox->setChecked(compilerSet.warningAllCheckBoxState);
    warningExtraCheckBox->setChecked(compilerSet.warningExtraCheckBoxState);
    modeComboBox->setCurrentIndex(compilerSet.modeIndex);

    QListWidget *binListWidget = directoriesWidget->getBinListWidget();
    binListWidget->clear();
    foreach (QString str, compilerSet.binList)
        binListWidget->addItem(str);

    for (int i = 0; i < binListWidget->count(); i++)
        binListWidget->item(i)->setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled);

    QListWidget *libListWidget = directoriesWidget->getLibListWidget();
    libListWidget->clear();
    foreach (QString str, compilerSet.libList)
        libListWidget->addItem(str);

    for (int i = 0; i < libListWidget->count(); i++)
        libListWidget->item(i)->setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled);

    QListWidget *cIncludeListWidget = directoriesWidget->getCIncludeListWidget();
    cIncludeListWidget->clear();
    foreach (QString str, compilerSet.cIncludeList)
        cIncludeListWidget->addItem(str);

    for (int i = 0; i < cIncludeListWidget->count(); i++)
        cIncludeListWidget->item(i)->setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled);

    QListWidget *cppIncludeListWidget = directoriesWidget->getCppIncludeListWidget();
    cppIncludeListWidget->clear();
    foreach (QString str, compilerSet.cppIncludeList)
        cppIncludeListWidget->addItem(str);

    for (int i = 0; i < cppIncludeListWidget->count(); i++)
        cppIncludeListWidget->item(i)->setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled);
}

void CompileOptionDialog::fileButtonClicked()
{
    QString selectedPath = QFileDialog::getOpenFileName(this, "Open file", "");
    if (selectedPath.isEmpty()) return;

    QPushButton *clickedButton = dynamic_cast<QPushButton *>(sender());
    if (clickedButton == gccButton)
        gccLineEdit->setText(selectedPath);
    else if (clickedButton == gppButton)
        gppLineEdit->setText(selectedPath);
    else if (clickedButton == makeButton)
        makeLineEdit->setText(selectedPath);
    else if (clickedButton == gdbButton)
        gdbLineEdit->setText(selectedPath);
    else if (clickedButton == windresButton)
        windresLineEdit->setText(selectedPath);
    else if (clickedButton == gprofButton)
        gprofLineEdit->setText(selectedPath);
}

void CompileOptionDialog::okButtonClicked()
{
    int index = compilerComboBox->currentIndex();
    if (index >= 0 && compilerSetChanged(index))
        saveChangesToCompilerSet(index);

    writeSettings();

    this->accept();//OK按钮点击以后发出Accepted返回值
}

void CompileOptionDialog::writeSettings()
{
    QString appDataPath = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
    QSettings setting(appDataPath + "/Setting.ini", QSettings::IniFormat);

    int compilerCount = compilerComboBox->count();
    QList<CompilerSet> compilerSetList;

    for (int i = 0; i < compilerCount; i++)
    {
        CompilerSet compilerSet = compilerComboBox->itemData(i, Qt::UserRole).value<CompilerSet>();
        compilerSetList.append(compilerSet);
    }

    QVariant variant;
    variant.setValue(compilerSetList);
    setting.setValue("CompilerSet", variant);
    if (compilerCount < 1)
        setting.setValue("CurrentCompilerIndex", -1);
    else
        setting.setValue("CurrentCompilerIndex", compilerComboBox->currentIndex());

    setting.setValue("CompileMode", modeComboBox->currentText());
}

void CompileOptionDialog::cancelButtonClicked()
{
    this->reject();//Cancel按钮点击以后发出Rejected返回值
}

void CompileOptionDialog::compileArgCheckBoxStateChanged()
{
    compileArgTextEdit->setEnabled(compileArgCheckBox->isChecked());
}

void CompileOptionDialog::linkArgCheckBoxStateChanged()
{
    linkArgTextEdit->setEnabled(linkArgCheckBox->isChecked());
}

void CompileOptionDialog::compilerRenameButtonClicked()
{
    if (compilerComboBox->count() < 1)
    {
        QMessageBox::information(this, "Rename", tr("No compiler set to rename!"));
        return;
    }

    bool OK = false; //QInputDialog的确定按钮被点击，返回true，否则false;
    QString newName = QInputDialog::getText(this, "Compiler rename", "Please input a new name:", QLineEdit::Normal, compilerComboBox->currentText(), &OK);
    newName = newName.trimmed();
    if (OK && !newName.isEmpty())
    {
        if (compilerComboBox->findText(newName, Qt::MatchCaseSensitive) >= 0)
        {
            QMessageBox::information(this, "Information", newName + "\n\n"+tr("The above compiler already exists in list!")+"\n"+tr("Please input a different name!"));
            return;
        }

        CompilerSet compilerSet = compilerComboBox->itemData(compilerComboBox->currentIndex(), Qt::UserRole).value<CompilerSet>();
        compilerSet.compilerName = newName;
        QVariant myVariant = QVariant::fromValue(compilerSet); //将该结构体实例转换为QVariant
        compilerComboBox->setItemData(compilerComboBox->currentIndex(), myVariant, Qt::UserRole);

        compilerComboBox->setItemText(compilerComboBox->currentIndex(), newName);
    }
}

void CompileOptionDialog::addNewSetButtonClicked()
{
    bool OK = false; //QInputDialog的确定按钮被点击，返回true，否则false;
    QString newSetName = QInputDialog::getText(this, "New set name", "Enter the new set name:", QLineEdit::Normal, "", &OK);
    newSetName = newSetName.trimmed();
    if (OK && !newSetName.isEmpty())
    {
        if (compilerComboBox->findText(newSetName, Qt::MatchCaseSensitive) >= 0)
        {
            QMessageBox::information(this, "Information", newSetName + "\n\n"+tr("The above compiler already exists in list!")+"\n"+
                                                                       tr("Rename or delete existing compiler and try again!"));
            return;
        }

        CompilerSet compilerSet;
        compilerSet.compilerName = newSetName;
        compilerComboBox->addItem(newSetName);
        compilerComboBox->setCurrentText(newSetName);

        QVariant myVariant = QVariant::fromValue(compilerSet); //该结构体实例转换为QVariant
        compilerComboBox->setItemData(compilerComboBox->currentIndex(), myVariant, Qt::UserRole);
    }
}

void CompileOptionDialog::addSetFromPathButtonClicked()
{
    QString selectedPath = QFileDialog::getExistingDirectory(this, "Select a folder", "");
    if (selectedPath.isEmpty()) return;

    CompilerSet compilerSet;
    this->setEnabled(false);
    QApplication::processEvents(QEventLoop::ExcludeUserInputEvents); //执行本线程时同时更新界面，但禁止用户输入。
    GetDirNameList(selectedPath, compilerSet);
    this->setEnabled(true);
    if (compilerSet.compilerName.isEmpty())
    {
        QMessageBox::information(this, "Information", selectedPath + "\n\n"+tr("No MinGW compiler found in the above folder!"));
        return;
    }
    else if (compilerComboBox->findText(compilerSet.compilerName, Qt::MatchCaseSensitive) >= 0)
    {
        QMessageBox::information(this, "Information", compilerSet.compilerName + "\n\n"+tr("The above compiler already exists in list!")+"\n"+
                                                                                 tr("Rename or delete existing compiler and try again!"));
        return;
    }
    else
    {
        compilerComboBox->addItem(compilerSet.compilerName);
        compilerComboBox->setCurrentText(compilerSet.compilerName);
        QVariant myVariant = QVariant::fromValue(compilerSet); //该结构体实例转换为QVariant
        compilerComboBox->setItemData(compilerComboBox->currentIndex(), myVariant, Qt::UserRole);
        compilerComboBoxCurrentIndexChanged(compilerComboBox->currentIndex());
    }
}

void CompileOptionDialog::GetDirNameList(const QString &path, CompilerSet &compilerSet)
{
    if (QString::compare(QFileInfo(path).fileName(), "bin", Qt::CaseInsensitive) == 0)
    {
        if (findCompilerFromPath(path, compilerSet)) return;
    }

    QFileInfoList dirInfoList = QDir(path).entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
    foreach (QFileInfo dirInfo, dirInfoList)
    {
        if (QString::compare(dirInfo.fileName(), "bin", Qt::CaseInsensitive) == 0)
        {
            if (findCompilerFromPath(path, compilerSet)) return;
        }

        GetDirNameList(dirInfo.absoluteFilePath(), compilerSet);
    }
}

bool CompileOptionDialog::findCompilerFromPath(QString path, CompilerSet& compilerSet)
{
    QDir binDir(path);
    QFileInfo pathInfo(path);
    QStringList fileList = binDir.entryList(QDir::Files | QDir::NoDotAndDotDot);
    if (fileList.contains("gcc.exe", Qt::CaseInsensitive))
        compilerSet.gccFile = "gcc.exe";
    if (fileList.contains("gdb.exe", Qt::CaseInsensitive))
        compilerSet.gdbFile = "gdb.exe";
    if (fileList.contains("windres.exe", Qt::CaseInsensitive))
        compilerSet.windresFile = "windres.exe";
    if (fileList.contains("gprof.exe", Qt::CaseInsensitive))
        compilerSet.gprofFile = "gprof.exe";
    if (fileList.contains("g++.exe", Qt::CaseInsensitive))
    {
        compilerSet.gppFile = "g++.exe";
        foreach (QString str, fileList)
        {
            if (str.contains("make.exe", Qt::CaseInsensitive)) compilerSet.makeFile = str;
        }

        compilerSet.compilerName = QFileInfo(pathInfo.path()).fileName();

        compilerSet.binList.append(path);
        QString libPath = pathInfo.path() + "/lib";
        if (QFileInfo::exists(libPath)) compilerSet.libList.append(libPath);
        QString includePath = pathInfo.path() + "/include";
        if (QFileInfo::exists(includePath))
        {
            compilerSet.cIncludeList.append(includePath);
            compilerSet.cppIncludeList.append(includePath);
        }
        return true;
    }
    return false;
}
void CompileOptionDialog::questionButtonClicked()
{
    QString colorStr=QString("<span style=color:%1>").arg(GlobalVar::defaultStringColor[GlobalVar::colorTheme].name());

    QMessageBox msg(this);
    msg.setIcon(QMessageBox::NoIcon);
    msg.setWindowTitle("编译模式说明");
    msg.setText(QString("%1自定义模式(Custom)</span>：不自动添加编译模式选项，开发者可自行在编译选项框中添加编译方式，优化等级，"
                        "警告级别和路径设定等选项，灵活定制编译方案，适合对MinGW编译器较为熟悉的开发者。<br/><br/>"
                "%2调试模式(Debug)</span>：通常在程序开发和调试过程中使用，编译时会添加 -g3 -Og 选项，产生的可执行文件中包含行号，"
                "变量的跟踪信息和详细的错误报告等，方便进行断点设置、单步跟踪等操作，可打开GDB进行调试。<br/><br/>"
                "%3性能分析模式(Profile)</span>：测试程序中各函数执行性能时使用。编译时会添加 -pg -no-pie -DNDEBUG -O2 选项，当程序编译&运行结束后"
                "会产生性能分析报告gmon.out文件，点击\"运行\"菜单中的性能分析，可显示程序中各函数的运行次数，运行耗时以及函数之间的调用图。"
                "函数运行时间低于0.01秒将显示为0或不显示。<br/><br/>"
                "%4发行模式(Release)</span>：通常在软件产品最终发布时使用。编译时会添加 -DNDEBUG -O3选项，优化等级最高，关闭断言提高性能。"
                "程序运行速度一般会远超调试模式，文件大小也小于调试模式。").arg(colorStr, colorStr, colorStr, colorStr));
    msg.exec();
}

void CompileOptionDialog::removeSetButtonClicked()
{
    if (compilerComboBox->count() < 1) return;

    QMessageBox::StandardButton result = QMessageBox::question(this, "Remove", compilerComboBox->currentText() +
                                                                "\n\n"+tr("Are you sure to remove the above Compiler set?"),
                                                                QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
    if (result == QMessageBox::Yes)
    {
        compilerComboBox->removeItem(compilerComboBox->currentIndex());
    }
}
